<?php 
/**
 * minf - core library
 * functions.php
 *
 * @author per function || minf.org team
 * @version 0.beta4
 * @copyright no,no,left, minf.org, 25 February, 2009
 * @license GPL
 * @package default
 **/

/**
 * ATTENTION (Minf Developers) : 
 * 
 * 		This file is also a sample for coding style and documentation style.
 * 	You should code like this.
 *
 *		Suggestions to : info - minf.org
 *		Modifications to (as uncompressed attachments) : mod - minf.org
 *
 **/

/**
 * reads the specified config file (look /doc/samples/sample.cfg for template)
 *
 * @param String $path Path of Config File
 * @param Array $oldconf Optional - Configuration to continue on
 * @return Array Containing config
 * @author Furkan Mustafa - furkan@minf.org - 2.2009
 **/
function parseCfgFile($path, $oldconf=array()) {
	$returnarray = $oldconf;
	if (!file_exists($path)) return false; // file doesnt exist
	$data = explode("\n", file_get_contents($path));
	foreach($data as $ln=>$line) {
		$line = trim($line);
		if ( (substr($line,0,1)=="#") || (strlen($line)<1) || ( (!strpos($line, "\t")) && (!substr($line,0,1)=="[") ) ) unset($data[$ln]);
		else $data[$ln] = $line;
	}
	
	foreach($data as $ln=>$line) {
		if (substr($line,0,1)=="[") {
			if ($lasttitle&&$titleadd) {
				$returnarray[$lasttitle][] = $tempsubitem;
			}
			$lasttitle = substr($line,1,-1);
			if (substr($lasttitle,0,1)==".") list($lasttitle, $titleadd, $tempsubitem) = array(substr($lasttitle,1), true, array());
				else $titleadd = false;
		}else{
			$parts = explode("\t", $line);
			foreach ($parts as $pn=>$part) {
				$part = trim($part);
				if (sizeof($part)<1) unset($parts[$pn]);
				else $parts[$pn] = $part;
			}
			$key = false;
			$val = false;
			foreach($parts as $part)
				if (!$key) $key = $part;
				else $val = $part;
			if (substr($key,0,1)=="!") {
				$key = substr($key,1);
				if ($lasttitle) unset($returnarray[$lasttitle][$key]);
				else unset($returnarray[$key]);
			}
			if ($lasttitle&&!$titleadd) {
				if (!$returnarray[$lasttitle][$key])
					$returnarray[$lasttitle][$key] = $val;
				elseif (is_array($returnarray[$lasttitle][$key]))
					$returnarray[$lasttitle][$key][] = $val;
				else
					$returnarray[$lasttitle][$key] = array($returnarray[$lasttitle][$key], $val);
			}elseif ($lasttitle&&$titleadd) {
				if (!$tempsubitem[$key])
					$tempsubitem[$key] = $val;
				elseif (is_array($tempsubitem[$key]))
					$tempsubitem[$key][] = $val;
				else
					$tempsubitem[$key] = array($tempsubitem[$key], $val);				
			}else{
				if (!$returnarray[$key])
					$returnarray[$key] = $val;
				elseif (is_array($returnarray[$key]))
					$returnarray[$key][] = $val;
				else
					$returnarray[$key] = array($returnarray[$key], $val);
			}
		}
	}
	if ($lasttitle&&$titleadd) {
		$returnarray[$lasttitle][] = $tempsubitem;
	}
	return $returnarray;
}

/**
 * Returns Filelist in Directory
 *
 * @param String $Path
 * @return Array Filelist || False on Failure
 */
function dirList($Path) {
	if (is_dir($Path)) {
		if ($dh = opendir($Path)) {
			$ret = array();
			while (($file = readdir($dh)) !== false) {
				if (substr($file,0,1)!=".")
					array_push($ret, $file);
			}
			closedir($dh);
			return $ret;
		}else{
			return false;
		}
	}else{
		return false;
	}
}

/**
 * Includes all .php files in a directory
 * note : this function needs dirList function from core/functions.php @minf >= 0.2.b5
 *
 * @param String $Path
 * @return Boolean False on Failure
 */
function includeAll($path) {
	if (substr($path,-1)!="/") $path .= "/";
	$files = dirList($path);
	if (!$files) return false;
	foreach ($files as $_file) {
		if (substr($_file,-3,3)=="php")
			if (!include_once($path.$_file))
				return false;
	}
	return true;
}

/* Message Level Definings to use with following function */
define(MSG_NOTICE, 0);
define(MSG_WARNING, 1);
define(MSG_ERROR, 2);
define(MSG_QUERY, 3);
define(MSG_FQUERY, 4);

/**
 * Adds a message to System Log (with grabbing microtime)
 *
 * @param String $message
 * @param Integer $level MSG_NOTICE or MSG_WARNING or MSG_ERROR
 */
function echosys($message, $level = MSG_NOTICE, $desc = null) {
	global $messages;
	if (!is_array($messages)) $messages = array();
	
	$messages[] = array(
		"time"=>microtime(true),
		"text"=>$message,
		"level"=>$level,
		"desc"=>$desc
		);
	if ($level==MSG_ERROR||$level==MSG_FQUERY||$level==MSG_WARNING) return false;
	return true;
}

/**
 * Allows multiple expressions to be tested on one string.
 * This will return a boolean, however you may want to alter this.
 *
 * @author William Jaspers, IV <wjaspers4@gmail.com>
 * @created 2009-02-27 17:00:00 +6:00:00 GMT
 * @access public
 *
 * @param array $patterns An array of expressions to be tested.
 * @param String $subject The data to test.
 * @param array &$findings Optional argument to store our results.
 * @param mixed $flags Pass-thru argument to allow normal flags to apply to all tested expressions.
 * @param array &$errors A storage bin for errors
 *
 * @returns bool Whether or not errors occurred.
 */
function preg_match_multiple( 
  array $patterns=array(), 
  $subject=null,
  &$findings=array(),
  $flags=false,
  &$errors=array()
) {
  foreach( $patterns as $name => $pattern )
  {
    if( 1 <= preg_match_all( $pattern, $subject, $found, $flags ) )
    {
      $findings[$name] = $found;
    } else 
    {
      if( PREG_NO_ERROR !== ( $code = preg_last_error() ))
      {
        $errors[$name] = $code;
      } else $findings[$name] = array();
    }
  }
  return (0===sizeof($errors));
}

/**
 * Sorts an array by a subkey
 *
 * @author quirk at qns dot se
 * @link http://www.php.net/manual/en/function.sort.php#76602
 *
 * @param array $original Array to sort
 * @param String $field Key
 * @param Boolean $descending (Optional)
 *
 * @returns array
 */
function sortArrayByField ($original, $field, $descending = false) {
    $sortArr = array();
    
    foreach ($original as $key => $value)
        $sortArr[$key] = $value[$field];

    if ($descending)
        arsort($sortArr);
    else
        asort($sortArr);
    
    $resultArr = array();
    foreach ($sortArr as $key => $value)
        $resultArr[$key] = $original[$key];

    return $resultArr;
}

/**
 * Shows fatal error for minf
 * 
 * @param String $msg Error Message
 */
function fatal ($msg) {
	die("MINF: FATAL ERROR: $msg");
}

/**
 * multiplies a string
 *
 * @param String $str string to be multiplied
 * @param Integer $n counts of occurences
 */
function strn($str, $n) {
	$r = "";
	for (;$n>0;$n--) $r .= $str;
	return $r;
}

/**
 * checks ($arr[*][$key]==$val) returns matched $arr subitem
 *
 * @param Array $arr Haystack
 * @param String $key To Match
 * @param mixed $val To Match
 * @return mixed or false
 */
function array_subkey_exists($arr, $key, $val) {
	foreach ($arr as $a) if ($a[$key]==$val) return $a;
	return false;
}


/**
 * deserializer for simple serialization mentioned in docs/dataformats/simpleser.txt
 * simple enough to write in hand to database etc.
 * good for keeping permissions etc. in it
 *
 * @param String $ConfigLine
 * @return Array parsed
 */
function array_parseconfig($ConfigLine) {
	$ToReturn = array();
	$ParsedConfig = explode(",", $ConfigLine);
	
	foreach ($ParsedConfig as $_parsed) {
		$_parsed = trim($_parsed);
		if (strpos($_parsed, " ")!==false) {
			$_pieces = explode(" ", $_parsed);
			$ToReturn[$_pieces[0]][$_pieces[1]][] = $_pieces[2] ? $_pieces[2] : "*";
		}else{
			$ToReturn[$_parsed] = array("*"=>array("*"));
		}
	}
	return $ToReturn;
}

// returns a value from conf
function conf($varn) {
	global $conf;

	if (!is_string($varn)) return false;
	
	if (strpos($varn, ".")===false) {
		$toset = &$conf[$varn];
	} else {
		$pt = explode(".", $varn);
		if (sizeof($pt)==2&&isset($conf[$pt[0]][$pt[1]])) $toset = &$conf[$pt[0]][$pt[1]];
		elseif (sizeof($pt)==3&&isset($conf[$pt[0]][$pt[1]][$pt[2]])) $toset = &$conf[$pt[0]][$pt[1]][$pt[2]];
		elseif (sizeof($pt)==4&&isset($conf[$pt[0]][$pt[1]][$pt[2]][$pt[3]])) $toset = &$conf[$pt[0]][$pt[1]][$pt[2]][$pt[3]];
	}
	return $toset ? $toset : false;
}

function checkconf($varn, $value) {
	$v = conf($varn);
	if (!$v) return false;
	if ($v==$value) return true;
	if (is_array($v)&&in_array($value, $v)) return true;
	return false;
}

?>